package com.mes.schedule.domain;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 设备
 * date: Jun 22, 2015 5:02:07 PM <br/>  
 * @author Administrator  
 * @version   
 * @since JDK 1.6
 */
public class SDevice extends Resource implements Serializable,Cloneable  {

	private static final long serialVersionUID = 1L;
	private final static Log log = LogFactory.getLog(SDevice.class);
	public final static int DEVICESTATE_RUNNING = 1;
	public final static int DEVICESTATE_IDLE = 2;
	public final static int DEVICESTATE_MAINTENANCE = 3;

	// true表示是否应用顺序公平策略
	// 主要用于多代理应用程序
	// 只在dtAssignManager中应用，应该移出
	public final ReentrantLock deviceAssignLock = new ReentrantLock(true);
	public final Condition condDeviceRun = deviceAssignLock.newCondition();

	/**
	 * 	 已就绪设备任务队列
	 */
	protected volatile SortedSet<SOperationTask> readyTaskQueue;
	
	/**
	 * 	 已取消设备任务队列
	 */
	protected volatile List<SOperationTask> cancelTaskList;
	
//	/**
//	 * 做能力计划的设备
//	 * 
//	 */
//	protected SDevice calCapacityDevice;

	// 仅用于设备是否有readyTask的锁
	// public AtomicBoolean readyTaskObjectLock = new AtomicBoolean(true);

	public List<SOperationTask> getCancelTaskList() {
		return cancelTaskList;
	}

//	public SDevice getCalCapacityDevice() {
//		return calCapacityDevice==null?this:calCapacityDevice;
//	}
//
//	public void setCalCapacityDevice(SDevice calCapacityDevice) {
//		this.calCapacityDevice = calCapacityDevice;
//	}

	public void setCancelTaskList(List<SOperationTask> cancelTaskList) {
		this.cancelTaskList = cancelTaskList;
	}

	@Override
	public String getResName() {
		return this.getDeviceName();
	}
	@Override
	public String getResUid() {
		return this.getDeviceUid();
	}
	public String toString() {
		// TODO Auto-generated method stub
	
		return " 编号=" + this.deviceUid + " 名称=" + this.deviceName;
	}

	// public TreeSet<SOperationTask> getMaybeTaskQueue() {
	// return maybeTaskQueue;
	// }
	//
	// public void setMaybeTaskQueue(TreeSet<SOperationTask> maybeTaskQueue) {
	// this.maybeTaskQueue = maybeTaskQueue;
	// }

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final SDevice other = (SDevice) obj;
		if (deviceUid == null) {
			if (other.deviceUid != null)
				return false;
		} else if (!deviceUid.equals(other.deviceUid))
			return false;
		return true;
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return super.hashCode();
	}

	// @Override
	// public int getSegementUse(int segement) {
	// // // TODO Auto-generated method stub
	// // if(segement<this.deviceEarlyStartSegement)
	// // return Resource.RESOURCE_PROCESS; //不允许在最早开始时间进行任何安排
	// // else
	// return super.getSegementUse(segement);
	// }
	// 应该放在日历对象中
	public final static int DEVICE_OVERTIME = 2;

	public final static int DEVICE_NOMAL = 1;

	public final static int DEVICE_CLOSINGTIME = 0;

	public final static int DEVICE_BREAKDOWN = -1;

	public final static int DEVICE_IDLE = 0;

	public final static int DEVICE_PROCESS = 1;

	public final static int DEVICE_SETUP = 2;

	protected String deviceUid;

	protected String deviceId;

	protected String deviceName;
	protected String modelName;// 设备型号

	/**
	 * 设备类：工作中心
	 */
	protected String deviceClass;
	/**
	 * 工作中心名称
	 */
	protected String deviceClassName;

	/**
	 * 设备状态=1
	 */
	protected int deviceState = 1;

	protected String deptUid;
	/**
	 * 设备能力=1
	 */
	protected int resCapacity=1;



	/**
	 * 工作台数量=1
	 */
	protected int tableCount = 1;

	protected TreeMap<TimeSection, SOperationTask> operTask;

	protected List<DeviceStatistics> deviceStatList;

	protected double averageLoadRation;

	protected double averageUtilRation;

	protected double totalRunTime;

	protected double totalIdleTime;

	protected double totalSetupTime;

	protected double totalOverTime;

	protected double utilRation;

	protected double totalWaitTime;

	protected String sWorkCenterUid;
	protected SWorkCenter sWorkCenter;
	


	/*
	 * 设备上的最早开始时间限制，主要用于序列或者其它设备约束
	 */
	// protected int deviceEarlyStartSegement;
	/*
	 * 设备上由于序列而产生的最早开始时间限制
	 */
	protected int deviceSeqEarlyStartSegement;

	// todo
	// 以后应该用更强的风险系数取代
	protected int notRobustCount;
	// 已分派任务队列
	protected TreeSet<SOperationTask> assignedTaskQueue;

	// 可能的设备任务队列
	// protected TreeSet<SOperationTask> maybeTaskQueue;

	protected TreeSet<SOperationTask> interruptDeviceQueue;

	// 等待中设备任务队列
	protected volatile List<SOperationTask> waitingTasks;
	
	
	/**
	 * 仅用于仿真
	 */
	public int calDeviceCurrentSegment;

	// /*
	// * 正在进行的任务
	// */
	// protected SOperationTask runningTask;

	public void addToQueue(SOperationTask operationTask) {

		// if (operationTask.getTaskUid().equals(
		// "3787238")
		//
		// ) {
		// System.out.println("********************添加进设备集合:"+operationTask );
		//
		// }
		synchronized (this) {
			
		
		try {
			
			if (operationTask != null && operationTask.getPlanFinish() != null)
				this.assignedTaskQueue.add(operationTask);
			else {
				log.warn("whyfs");
			}
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			log.error("aaaaaaaaaaaaaaaaaaaaaaaa" + operationTask);
			
			e.printStackTrace();
		}
		}
	}

	public SDevice() {

		deviceStatList = new ArrayList<DeviceStatistics>();

		// 设备队列
		class DeviceSeqComparator implements Comparator<SOperationTask>,
				Serializable {
			public int compare(SOperationTask operTask1,
					SOperationTask operTask2) {
				int i = 1;
				if (operTask1.equals(operTask2))
					return 0;
				if (operTask1.getCalDeviceSeq() < operTask2.getCalDeviceSeq())
					i = -1;
				return i;
			}
		}
		interruptDeviceQueue = new TreeSet<SOperationTask>(
				new DeviceSeqComparator());

		// // 设备队列
		// this.maybeTaskQueue = new TreeSet<SOperationTask>(
		// new Comparator<SOperationTask>() {
		// public int compare(SOperationTask operTask1,
		// SOperationTask operTask2) {
		// int i = 1;
		// if (operTask1.equals(operTask2))
		// return 0;
		// i = compareSeq(operTask1, operTask2);
		// if (i == 0) {
		// i = operTask1.getScheme()
		// .getOperationTaskComparator().compare(
		// operTask1, operTask2);
		// }
		// return i;
		// }
		// });

		// waitingTasks = new HashSet<SOperationTask>();

		/*
		 * 设备任务队列
		 */
		/**
		 * 2014-07-31 用开始时间来作为排序规则不太好 应用用finish,因为存在多工作台的问题
		 */
		// 设备队列
		class AssnTaskComparator implements Comparator<SOperationTask>,
				Serializable {
			public int compare(SOperationTask operTask1,
					SOperationTask operTask2) {
				int i = -1;
				try {
					if (operTask1.equals(operTask2))
						return 0;

					if (operTask1.getPlanFinish() != null
							&& operTask2.getPlanFinish() != null
							&& operTask1.getPlanFinish().after(
									operTask2.getPlanFinish()))
						i = 1;
				} catch (Exception e) {
					// TODO Auto-generated catch block
					log.error("插入设备分配队列时发生错误！", e);
				}

				return i;
			}
		}
		assignedTaskQueue = new TreeSet<SOperationTask>(
				new AssnTaskComparator());
	}

	/**
	 * @return the deviceUid
	 */
	public String getDeviceUid() {
		return deviceUid;
	}

	/**
	 * @param deviceUid
	 *            the deviceUid to set
	 */
	public void setDeviceUid(String deviceUid) {
		this.deviceUid = deviceUid;
	}

	/**
	 * @return the deviceName
	 */
	public String getDeviceName() {
		return deviceName;
	}

	/**
	 * @param deviceName
	 *            the deviceName to set
	 */
	public void setDeviceName(String deviceName) {
		this.deviceName = deviceName;
	}

	/**
	 * @return the deviceClass
	 */
	public String getDeviceClass() {
		return deviceClass;
	}

	/**
	 * @param deviceClass
	 *            the deviceClass to set
	 */
	public void setDeviceClass(String deviceClass) {
		this.deviceClass = deviceClass;
	}

	/**
	 * @return the deviceClassName
	 */
	public String getDeviceClassName() {
		return deviceClassName;
	}

	/**
	 * @param deviceClassName
	 *            the deviceClassName to set
	 */
	public void setDeviceClassName(String deviceClassName) {
		this.deviceClassName = deviceClassName;
	}

	/**
	 * @return the resCapacity
	 */
	public int getResCapacity() {
		return resCapacity;
	}

	/**
	 * @param resCapacity
	 *            the resCapacity to set
	 */
	public void setResCapacity(int resCapacity) {
		this.resCapacity = resCapacity;
	}



	/**
	 * @return the operTask
	 */
	public TreeMap<TimeSection, SOperationTask> getOperTask() {
		return operTask;
	}

	/**
	 * @param operTask
	 *            the operTask to set
	 */
	public void setOperTask(TreeMap<TimeSection, SOperationTask> operTask) {
		this.operTask = operTask;
	}

	/**
	 * @return the deviceStatList
	 */
	public List<DeviceStatistics> getDeviceStatList() {
		return deviceStatList;
	}

	/**
	 * @param deviceStatList
	 *            the deviceStatList to set
	 */
	public void setDeviceStatList(List<DeviceStatistics> deviceStatList) {
		this.deviceStatList = deviceStatList;
	}

	/**
	 * @return the averageLoadRation
	 */
	public double getAverageLoadRation() {
		return averageLoadRation;
	}

	/**
	 * @param averageLoadRation
	 *            the averageLoadRation to set
	 */
	public void setAverageLoadRation(double averageLoadRation) {
		this.averageLoadRation = averageLoadRation;
	}

	/**
	 * @return the averageUtilRation
	 */
	public double getAverageUtilRation() {
		return averageUtilRation;
	}

	/**
	 * @param averageUtilRation
	 *            the averageUtilRation to set
	 */
	public void setAverageUtilRation(double averageUtilRation) {
		this.averageUtilRation = averageUtilRation;
	}

	/**
	 * @return the totalRunTime
	 */
	public double getTotalRunTime() {
		return totalRunTime;
	}

	/**
	 * @param totalRunTime
	 *            the totalRunTime to set
	 */
	public void setTotalRunTime(double totalRunTime) {
		this.totalRunTime = totalRunTime;
	}

	/**
	 * @return the totalIdleTime
	 */
	public double getTotalIdleTime() {
		return totalIdleTime;
	}

	/**
	 * @param totalIdleTime
	 *            the totalIdleTime to set
	 */
	public void setTotalIdleTime(double totalIdleTime) {
		this.totalIdleTime = totalIdleTime;
	}

	/**
	 * @return the totalSetupTime
	 */
	public double getTotalSetupTime() {
		return totalSetupTime;
	}

	/**
	 * @param totalSetupTime
	 *            the totalSetupTime to set
	 */
	public void setTotalSetupTime(double totalSetupTime) {
		this.totalSetupTime = totalSetupTime;
	}

	/**
	 * @return the totalOverTime
	 */
	public double getTotalOverTime() {
		return totalOverTime;
	}

	/**
	 * @param totalOverTime
	 *            the totalOverTime to set
	 */
	public void setTotalOverTime(double totalOverTime) {
		this.totalOverTime = totalOverTime;
	}

	/**
	 * @return the utilRation
	 */
	public double getUtilRation() {
		return utilRation;
	}

	/**
	 * @param utilRation
	 *            the utilRation to set
	 */
	public void setUtilRation(double utilRation) {
		this.utilRation = utilRation;
	}

	/**
	 * @return the totalWaitTime
	 */
	public double getTotalWaitTime() {
		return totalWaitTime;
	}

	/**
	 * @param totalWaitTime
	 *            the totalWaitTime to set
	 */
	public void setTotalWaitTime(double totalWaitTime) {
		this.totalWaitTime = totalWaitTime;
	}

	public String getDeviceId() {
		return deviceId;
	}

	public void setDeviceId(String deviceId) {
		this.deviceId = deviceId;
	}

	public int getTableCount() {
		return tableCount;
	}

	public void setTableCount(int tableCount) {
		this.tableCount = tableCount;
	}

	public String getModelName() {
		return modelName;
	}

	public void setModelName(String modelName) {
		this.modelName = modelName;
	}

	public String getDeptUid() {
		return deptUid;
	}

	public void setDeptUid(String deptUid) {
		this.deptUid = deptUid;
	}

	public int getDeviceState() {
		return deviceState;
	}

	public void setDeviceState(int deviceState) {
		this.deviceState = deviceState;
	}

	public int getNotRobustCount() {
		return notRobustCount;
	}

	public void setNotRobustCount(int notRobustCount) {
		this.notRobustCount = notRobustCount;
	}

	// public Map<String, ResourceConstraint> getMaybeTaskMap() {
	// return maybeTaskMap;
	// }
	//
	// public void setMaybeTaskMap(Map<String, ResourceConstraint> maybeTaskMap)
	// {
	// this.maybeTaskMap = maybeTaskMap;
	// }

	public TreeSet<SOperationTask> getInterruptDeviceQueue() {
		return interruptDeviceQueue;
	}

	public void setInterruptDeviceQueue(
			TreeSet<SOperationTask> interruptDeviceQueue) {
		this.interruptDeviceQueue = interruptDeviceQueue;
	}

	public TreeSet<SOperationTask> getAssignedTaskQueue() {
		return assignedTaskQueue;
	}

	public void setAssignedTaskQueue(TreeSet<SOperationTask> assignedTaskQueue) {
		this.assignedTaskQueue = assignedTaskQueue;
	}

	public String getDeviceStateDesc() {
		String deviceStateDesc = "";
		switch (this.deviceState) {
		case 1:
			deviceStateDesc = "运行中";
			break;

		case 2:
			deviceStateDesc = "暂停中";
			break;
		case 3:
			deviceStateDesc = "维修中";
			break;

		}

		return deviceStateDesc;

	}

	public SWorkCenter getSWorkCenter() {
		return sWorkCenter;
	}

	public void setSWorkCenter(SWorkCenter workCenter) {
		sWorkCenter = workCenter;
	}

	public String getSWorkCenterUid() {
		return sWorkCenterUid;
	}
	/**
	 * 设置设备的工作中心唯一号
	 * @param workCenterUid
	 */
	public void setSWorkCenterUid(String workCenterUid) {
		sWorkCenterUid = workCenterUid;
	}

	public int getDeviceSeqEarlyStartSegement() {
		return deviceSeqEarlyStartSegement;
	}

	public void setDeviceSeqEarlyStartSegement(int deviceSeqEarlyStartSegement) {
		this.deviceSeqEarlyStartSegement = deviceSeqEarlyStartSegement;
	}

	// 多能力设备，与无限能力设备部能用序列
	public boolean canUseSeq() {
		if (this instanceof UcDevice || this instanceof McDevice)
			return false;

		return true;

	}

	public SortedSet<SOperationTask> getReadyTaskQueue() {
		return readyTaskQueue;
	}

	public void setReadyTaskQueue(SortedSet<SOperationTask> readyTaskQueue) {
		this.readyTaskQueue = readyTaskQueue;
	}

	public List<SOperationTask> getWaitingTasks() {
		return waitingTasks;
	}

	public void setWaitingTasks(List<SOperationTask> waitingTasks) {
		this.waitingTasks = waitingTasks;
	}

	public static void main(String[] args) {
		SDevice device = new SDevice();
		device.setDeviceUid("aaaaaaaaaaa");

		SOperationTask o1 = new SOperationTask();
		o1.setTaskUid("o1");

		device.assignedTaskQueue.add(o1);

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {

			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(device);
			oos.close();

			ByteArrayInputStream bis = new ByteArrayInputStream(bos
					.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			Object object = ois.readObject();
			ois.close();
			System.out.println(object);

			System.out
					.println(device.assignedTaskQueue.first() == (((SDevice) object).assignedTaskQueue
							.first()));

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		try {
			super.destroy();
			if (this.deviceStatList != null) {
				this.deviceStatList.clear();
				this.deviceStatList = null;
			}
			if (this.interruptDeviceQueue != null) {
				this.interruptDeviceQueue.clear();
				this.interruptDeviceQueue = null;
			}
			if (this.assignedTaskQueue != null) {
				this.assignedTaskQueue.clear();
				this.assignedTaskQueue = null;
			}
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public int getCalDeviceCurrentSegment() {
		return calDeviceCurrentSegment;
	}

	public void setCalDeviceCurrentSegment(int calDeviceCurrentSegment) {
		this.calDeviceCurrentSegment = calDeviceCurrentSegment;
	}





}
